package com.fancy.gateway.filter;

import com.fancy.common.dto.response.Result;
import com.fancy.gateway.util.JwtUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;

/**
 * 全局认证过滤器
 *
 * @author fancy
 */
@Slf4j
@Component
public class AuthenticationFilter extends AbstractGatewayFilterFactory<AuthenticationFilter.Config> {

    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private ObjectMapper objectMapper;

    private final AntPathMatcher pathMatcher = new AntPathMatcher();

    @Value("${auth.whitelist}")
    private String whitelistPathsStr;

    @Value("${auth.vip-paths}")
    private String vipPathsStr;

    public AuthenticationFilter() {
        super(Config.class);
    }

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            ServerHttpRequest request = exchange.getRequest();
            String path = request.getURI().getPath();

            log.debug("处理请求路径: {}", path);

            // 检查是否为白名单路径
            if (isWhitelistPath(path)) {
                log.debug("白名单路径，跳过认证: {}", path);
                return chain.filter(exchange);
            }

            // 获取Token
            String authHeader = request.getHeaders().getFirst("Authorization");
            String token = jwtUtils.getTokenFromHeader(authHeader);

            if (token == null) {
                log.warn("未提供认证Token: {}", path);
                return buildErrorResponse(exchange, 40101, "请重新登录");
            }

            // 验证Token
            if (!jwtUtils.validateToken(token)) {
                log.warn("Token验证失败: {}", path);
                return buildErrorResponse(exchange, 40101, "请重新登录");
            }

            // 检查Token是否过期
            if (jwtUtils.isTokenExpired(token)) {
                log.warn("Token已过期: {}", path);
                return buildErrorResponse(exchange, 40101, "请重新登录");
            }

//            // 检查VIP权限
//            if (isVipPath(path) && !jwtUtils.isVipUser(token)) {
//                log.warn("VIP权限不足: userId={}, path={}", jwtUtils.getUserIdFromToken(token), path);
//                return buildErrorResponse(exchange, 40301, "无访问权限");
//            }

            // 添加用户��息到请求头
            ServerHttpRequest modifiedRequest = request.mutate()
                    .header("X-User-Id", jwtUtils.getUserIdFromToken(token))
                    .header("X-Username", jwtUtils.getUsernameFromToken(token))
                    .header("X-User-Role", jwtUtils.getUserRoleFromToken(token))
                    .header("X-Membership-Type", jwtUtils.getMembershipTypeFromToken(token))
                    .header("X-Is-Vip", String.valueOf(jwtUtils.isVipUser(token)))
                    .build();

            log.debug("认证成功: userId={}, path={}", jwtUtils.getUserIdFromToken(token), path);

            return chain.filter(exchange.mutate().request(modifiedRequest).build());
        };
    }

    /**
     * 检查是否为白名单路径
     */
    private boolean isWhitelistPath(String path) {
        List<String> whitelistPaths = parsePathList(whitelistPathsStr);
        return whitelistPaths.stream().anyMatch(pattern -> pathMatcher.match(pattern, path));
    }

    /**
     * 检查是否为VIP路径
     */
    private boolean isVipPath(String path) {
        List<String> vipPaths = parsePathList(vipPathsStr);
        return vipPaths.stream().anyMatch(pattern -> pathMatcher.match(pattern, path));
    }

    /**
     * 解析配置中的路径列表
     */
    private List<String> parsePathList(String pathsStr) {
        if (pathsStr == null || pathsStr.trim().isEmpty()) {
            return Arrays.asList();
        }
        return Arrays.asList(pathsStr.split(","));
    }

    /**
     * 构建错误响应
     */
    private Mono<Void> buildErrorResponse(ServerWebExchange exchange, int code, String message) {
        ServerHttpResponse response = exchange.getResponse();
        response.setStatusCode(HttpStatus.UNAUTHORIZED);
        response.getHeaders().add("Content-Type", MediaType.APPLICATION_JSON_VALUE);

        Result<Object> result = Result.fail(code, message);

        try {
            String body = objectMapper.writeValueAsString(result);
            DataBuffer buffer = response.bufferFactory().wrap(body.getBytes(StandardCharsets.UTF_8));
            return response.writeWith(Mono.just(buffer));
        } catch (JsonProcessingException e) {
            log.error("构建错误响应失败", e);
            return response.setComplete();
        }
    }

    public static class Config {
        // 配置参数类，可以在路由配置中传递参数
    }
}
